@file:Suppress("DEPRECATION")

package com.example.kotlinlearningproject.ui.activity

import android.Manifest
import android.content.pm.PackageManager
import android.graphics.ImageFormat
import android.hardware.Camera
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge
import com.example.kotlinlearningproject.databinding.ActivityCameraBinding
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.Collections

// 本例子主要为过时的第一代Camera库，后续会有对应的camera2例子

class CameraActivity : ComponentActivity() {
    companion object{
        const val TAG = "CameraActivity"
        val PERMISSIONS: Array<String> = arrayOf(Manifest.permission.CAMERA,
            Manifest.permission.MANAGE_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE)
        const val PERMISSION_REQ_CODE = 1
        const val PREVIEW_HEIGHT = 480
        const val PREVIEW_WIDTH = 640
    }
    private lateinit var binding: ActivityCameraBinding
    private var mCamera: Camera? = null
    private var cameraId: Int = Camera.CameraInfo.CAMERA_FACING_FRONT

    private val pictureCallback = Camera.PictureCallback { data, _ ->
        Log.e(TAG,"Picture call back!")
        mCamera?.startPreview()
//        val pictureFile = File(Environment.getExternalStorageDirectory(), "camera-" + System.currentTimeMillis() + ".jpg")
        val pictureFile = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
            "IMG_${System.currentTimeMillis()}.jpg")
        try {
            val fos = FileOutputStream(pictureFile)
            fos.write(data)
            fos.close()
        } catch (e: java.lang.Exception) {
            Log.e(TAG,"pictureCallback failed: $e")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        if (hasPermissions()) {
            Log.e(TAG, "has permissions")
            initCamera()
        } else {
            Log.e(TAG, "no permissions")
            requestPermission()
        }
//        initCamera()
    }

    private fun initCamera() {
        // 这里一并初始化，否则预览不出现
        binding = ActivityCameraBinding.inflate(layoutInflater)
        setContentView(binding.root)
//        if (isCameraAvailable()) {
//            mCamera = getCamera()
//            setParameters(mCamera)
//        }
        initViewListener()
    }


    private fun initViewListener() {
        Log.e(TAG, "initViewListener")
        binding.svCamera.holder.let {
            it.setFormat(ImageFormat.NV21)
            it.addCallback(object : SurfaceHolder.Callback, Camera.PreviewCallback {
                override fun onPreviewFrame(data: ByteArray?, camera: Camera?) {
//                    Log.e(TAG,"onPreviewFrame")
                }

                override fun surfaceCreated(holder: SurfaceHolder) {
                    Log.e(TAG, "surfaceCreated")
                    try {
                        mCamera = Camera.open(cameraId)
                    } catch (e: Exception) {
                        cameraId = Camera.CameraInfo.CAMERA_FACING_BACK
                        mCamera = Camera.open(cameraId)
                    }

                    try {
                        mCamera!!.setPreviewDisplay(binding.svCamera.holder)
                    } catch (e: IOException) {
                        Log.e(TAG,"setPreviewDisplay FAILED: $e")
                    }
                }

                override fun surfaceChanged(
                    holder: SurfaceHolder,
                    format: Int,
                    width: Int,
                    height: Int
                ) {
                    Log.e(TAG, "surfaceChanged")
                    if (holder.surface == null) return

                    if (mCamera == null) return

                    try {
                        mCamera?.stopPreview()
                    } catch (e: java.lang.Exception) {
                        e.printStackTrace()
                    }
                    setParameters(mCamera)
                    mCamera?.startPreview()
                    mCamera?.setPreviewCallback(this)
                    setCameraDisplayOrientation()
                }

                override fun surfaceDestroyed(holder: SurfaceHolder) {
                    mCamera?.setPreviewCallback(null)
                    mCamera?.release()
                    mCamera = null
                }
            })
        }
//
//        val holder = binding.svCamera.holder
//        holder?.addCallback(object : SurfaceHolder.Callback {
//            override fun surfaceCreated(holder: SurfaceHolder) {
//                Log.e(TAG, "surfaceCreated")
//                setStartPreview(mCamera, holder);
//            }
//
//            override fun surfaceChanged(
//                holder: SurfaceHolder,
//                format: Int,
//                width: Int,
//                height: Int
//            ) {
//                Log.e(TAG, "surfaceChanged")
//                // nothing to do
//            }
//
//            override fun surfaceDestroyed(holder: SurfaceHolder) {
//                // nothing to do
//                Log.e(TAG, "surfaceChanged")
//            }
//        })
        // 拍照
        binding.btnCapture.setOnClickListener {
            Log.e(TAG,"拍照按下")
            taskPicture()
        }
    }

    private fun isCameraAvailable(): Boolean {
        val numberOfCameras = Camera.getNumberOfCameras()
        Log.e(TAG, "numberOfCameras: $numberOfCameras")
        return numberOfCameras != 0
    }

    private fun getCamera(): Camera? {
        var camera: Camera?
        try {
            camera = Camera.open(cameraId)
        } catch (e: Exception) {
            Log.e(TAG,"open camera failed: $e")
            cameraId = Camera.CameraInfo.CAMERA_FACING_BACK
            camera = Camera.open(cameraId)
        }
        return camera
    }

    private fun setParameters(camera: Camera?) {
        camera?.let {
            val params: Camera.Parameters = camera.parameters
            params.pictureFormat = ImageFormat.JPEG
            val size = Collections.max(params.supportedPictureSizes
            ) { lhs, rhs -> lhs.width * lhs.height - rhs.width * rhs.height }
            params.setPreviewSize(size.width, size.height)
//            params.focusMode = Camera.Parameters.FOCUS_MODE_AUTO

            Log.d(TAG,"MAX ZOOM: ${params.maxZoom}")
            Log.d(TAG,"ZOOM: ${params.zoom}")
            Log.d(TAG,"MAX isSmoothZoomSupported: ${params.isSmoothZoomSupported}")

            params.zoom = 30

            try {
                camera.parameters = params;    //在设置属性时，如果遇到未支持的大小时将会直接报错，故需要捕捉一样，做异常处理
            } catch (e: Exception) {
                Log.e(TAG,"setParameters failed: $e")
            }
        }
    }

    private fun setStartPreview(camera: Camera?, holder: SurfaceHolder?) {
        camera?.let {
            try {
                camera.setPreviewDisplay(holder)
//                camera.setDisplayOrientation(Surface.ROTATION_90)
                setCameraDisplayOrientation()
                camera.startPreview()
            } catch (e: IOException) {
                Log.e(TAG,"setStartPreview failed: $e")
            }
        }
    }

    private fun setCameraDisplayOrientation() {
        val info = Camera.CameraInfo()
        Camera.getCameraInfo(cameraId, info)
        val rotation = windowManager.defaultDisplay.rotation
        var degrees = 0
        when (rotation) {
            Surface.ROTATION_0 -> degrees = 0
            Surface.ROTATION_90 -> degrees = 90
            Surface.ROTATION_180 -> degrees = 180
            Surface.ROTATION_270 -> degrees = 270
        }
        var result: Int
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360
            result = (360 - result) % 360 // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360
        }
        mCamera!!.setDisplayOrientation(result)
    }

    private fun taskPicture() {
//        mCamera?.autoFocus { _, _ ->
//
//        }
        run {
            mCamera?.takePicture(null, null, pictureCallback);
        }
    }

    private fun releaseCamera() {
        mCamera?.setPreviewCallback(null)
        mCamera?.stopPreview()
        mCamera?.release()
        mCamera = null
    }

    override fun onDestroy() {
        super.onDestroy()
        releaseCamera()
    }

    private fun requestPermission() = requestPermissions(PERMISSIONS, PERMISSION_REQ_CODE)

    private fun hasPermissions(): Boolean {
        for (permission in PERMISSIONS) {
            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "has NO Permissions!!!!")
                return false
            }
        }
        return true
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        Log.e(TAG, "onRequestPermissionsResult")
        if (requestCode == PERMISSION_REQ_CODE) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "onRequestPermissionsResult: ready to init camera")
                initCamera()
            } else {
                Toast.makeText(this, "请授权相关权限", Toast.LENGTH_LONG).show()
            }
        }
    }
}